package org.gordonframework.core.graphics {
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.geom.Matrix;	

	/**
	 * @author sampet
	 */
	public class GDraw {

		public static function arc(graphics:Graphics, width:Number, height:Number, startAngle:Number, arcAngle:Number, tx:Number = 0, ty:Number = 0):void {
			var curveCount:int = Math.ceil( Math.abs( arcAngle ) / 0.125 );
			var curveLength:Number = arcAngle / curveCount;	
			graphics.moveTo( tx + Math.cos( startAngle ) * width, ty + Math.sin( startAngle ) * height );
			for(var i:uint = 0; i < curveCount ; i++) {
				startAngle += curveLength;
				graphics.curveTo( tx + Math.cos( startAngle - (curveLength * 0.5) ) * (width / Math.cos( curveLength * 0.5 )), ty + Math.sin( startAngle - (curveLength * 0.5) ) * (height / Math.cos( curveLength * 0.5 )), tx + Math.cos( startAngle ) * width, ty + Math.sin( startAngle ) * height );
			}
		}

		public static function polygon(graphics:Graphics, width:Number, height:Number, sides:int, angle:Number = 0, tx:Number = 0, ty:Number = 0):void {
			var sideAngle:Number = Math.PI * 2 / sides;	
			graphics.moveTo( tx + Math.cos( angle ) * width, ty + Math.sin( angle ) * height );
			for(var i:uint = 0; i < sides ; i++) {
				angle += sideAngle;
				graphics.lineTo( tx + Math.cos( angle ) * width, ty + Math.sin( angle ) * height );		
			}
		}

		public static function rect(graphics:Graphics, width:Number, height:Number, roundness:Number = 0, tx:Number = 0, ty:Number = 0):void {
			if(roundness > 0) {
				rectComplex( graphics, width, height, roundness, roundness, roundness, roundness, tx, ty );
			} else {
				graphics.drawRect( tx, ty, width, height );
			}
		}

		public static function rectComplex(graphics:Graphics, width:Number, height:Number, topLeftRoundness:Number, topRightRoundness:Number, bottomLeftRoundness:Number, bottomRightRoundness:Number, tx:Number = 0, ty:Number = 0):void {
			graphics.moveTo( tx + topLeftRoundness, ty );
			graphics.lineTo( tx + width - topRightRoundness, ty );
			graphics.curveTo( tx + width, ty, tx + width, ty + topRightRoundness );
			graphics.lineTo( tx + width, ty + height - bottomRightRoundness );
			graphics.curveTo( tx + width, ty + height, tx + width - bottomRightRoundness, ty + height );
			graphics.lineTo( tx + bottomLeftRoundness, ty + height );
			graphics.curveTo( tx, ty + height, tx, ty + height - bottomLeftRoundness );
			graphics.lineTo( tx, ty + topLeftRoundness );
			graphics.curveTo( tx, ty, tx + topLeftRoundness, ty );
		}

		public static function bitmapTransform(graphics:Graphics, source:BitmapData, vertices:Array, rows:uint = 4, cols:uint = 4, smooth:Boolean = false):void {
			//Global matrix.
			var gm:Matrix = new Matrix( );
			//Local matrix.
			var lm:Matrix = new Matrix( );
			
			//Mesh width.
			var mw:Number = source.width / cols;
			//Mesh height.
			var mh:Number = source.height / rows;	
			
			var x1:Number = vertices[0].x;
			var y1:Number = vertices[0].y;
			
			var x2:Number = vertices[2].x;
			var y2:Number = vertices[2].y;
			
			var w1:Number = vertices[1].x - vertices[0].x;
			var h1:Number = vertices[1].y - vertices[0].y;
			
			var w2:Number = vertices[3].x - vertices[2].x;
			var h2:Number = vertices[3].y - vertices[2].y;	
			
			for(var i:uint = 0; i < cols ; i++) {
				
				//Column 1, point 1
				var c1x1:Number = x1 + w1 * (i / cols);
				var c1y1:Number = y1 + h1 * (i / cols);
				
				//Column 1, point 2			
				var c1x2:Number = x2 + w2 * (i / cols);
				var c1y2:Number = y2 + h2 * (i / cols);
				
				//Column 2, point 1
				var c2x1:Number = x1 + w1 * ((i + 1) / cols);
				var c2y1:Number = y1 + h1 * ((i + 1) / cols);
				
				//Column 2, point 2			
				var c2x2:Number = x2 + w2 * ((i + 1) / cols);
				var c2y2:Number = y2 + h2 * ((i + 1) / cols);
					
				for(var j:uint = 0; j < rows ; j++) {			
					
					//Local vertice 1
					var v1x:Number = c1x1 + (c1x2 - c1x1) * (j / rows);
					var v1y:Number = c1y1 + (c1y2 - c1y1) * (j / rows);
					
					//Local vertice 2
					var v2x:Number = c2x1 + (c2x2 - c2x1) * (j / rows);
					var v2y:Number = c2y1 + (c2y2 - c2y1) * (j / rows);
					
					//Local vertice 3
					var v3x:Number = c1x1 + (c1x2 - c1x1) * ((j + 1) / rows);
					var v3y:Number = c1y1 + (c1y2 - c1y1) * ((j + 1) / rows);			
					
					//Local vertice 4
					var v4x:Number = c2x1 + (c2x2 - c2x1) * ((j + 1) / rows);
					var v4y:Number = c2y1 + (c2y2 - c2y1) * ((j + 1) / rows);		
					
					lm.a = (v2x - v1x) / mw;
					lm.b = (v2y - v1y) / mw;
					lm.c = (v4x - v2x) / mh;
					lm.d = (v4y - v2y) / mh;
					lm.tx = v1x;
					lm.ty = v1y;
					
					gm.identity( );
					gm.tx = i * -mw;
					gm.ty = j * -mh;
					gm.concat( lm );
					
					graphics.beginBitmapFill( source, gm, false, smooth );
					graphics.moveTo( v1x, v1y );
					graphics.lineTo( v2x, v2y );
					graphics.lineTo( v4x, v4y );
					graphics.lineTo( v1x, v1y );
					graphics.endFill( );
					
					lm.a = (v4x - v3x) / mw;
					lm.b = (v4y - v3y) / mw;
					lm.c = (v3x - v1x) / mh;
					lm.d = (v3y - v1y) / mh;
					lm.tx = v1x;
					lm.ty = v1y;
					
					gm.identity( );
					gm.tx = i * -mw;
					gm.ty = j * -mh;
					gm.concat( lm );
					
					graphics.beginBitmapFill( source, gm, false, smooth );
					graphics.moveTo( v1x, v1y );
					graphics.lineTo( v3x, v3y );
					graphics.lineTo( v4x, v4y );
					graphics.lineTo( v1x, v1y );
					graphics.endFill( );	
				}
			}
		}		
	}
}
